<?php

declare(strict_types=1);

namespace App\Endpoint\Temporal\Workflow;

use App\Endpoint\Temporal\Activity\PingWebsiteActivity;
use App\Endpoint\Temporal\Activity\SendNotificationActivity;
use Carbon\CarbonInterval;
use Temporal\Activity\ActivityOptions;
use Temporal\Internal\Workflow\ActivityProxy;
use Temporal\Promise;
use Temporal\Workflow;
use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;

#[WorkflowInterface]
class WebsiteStatusWorkflow
{
    private bool $isDownNotified = false;
    private bool $isRecoveryNotified = false;
    private int $downTime = 0;

    private PingWebsiteActivity|ActivityProxy $pingActivity;
    private SendNotificationActivity|ActivityProxy $mailActivity;

    public function __construct()
    {
        $this->pingActivity = Workflow::newActivityStub(
            PingWebsiteActivity::class,
            ActivityOptions::new()
                ->withStartToCloseTimeout(5)
        );

        $this->mailActivity = Workflow::newActivityStub(
            SendNotificationActivity::class,
            ActivityOptions::new()
                ->withStartToCloseTimeout(5)
                ->withTaskQueue('mailer')
        );
    }

    /**
     * Handle workflow
     */
    #[WorkflowMethod]
    public function handle(string $url, int $intervalInMinutes = 5)
    {
        while (true) {
            // here we will ping the website and get the status
            $status = yield $this->pingActivity->ping($url);
            $status = yield $this->pingActivity->pingFromEurope($url);
            $status = yield $this->pingActivity->pingFromAsia($url);
            $status = yield $this->pingActivity->pingFromAmerica($url);

            [$statusEurope, $statusAsia, $statusAmerica] = yield Promise::all([
                $this->pingActivity->pingFromEurope($url),
                $this->pingActivity->pingFromAsia($url),
                $this->pingActivity->pingFromAmerica($url),
            ]);

            if ($status === false) {
                // Send notification only once when the website goes down
                if (!$this->isDownNotified) {
                    // here we will send a notification about downtime
                    yield $this->mailActivity->sendFailedNotification($url);
                }

                $this->isDownNotified = true;
                // increase downtime by 5 minutes
                $this->downTime += $intervalInMinutes;
            } else {
                // Send notification only once when the website goes up
                if (!$this->isRecoveryNotified) {
                    // here we will send a notification about recovery with total downtime
                    yield $this->mailActivity->sendRecoveryNotification($url, $this->downTime);
                }

                $this->downTime = 0;
                $this->isRecoveryNotified = true;
            }

            // wait for 5 minutes
            yield Workflow::timer(CarbonInterval::minutes($intervalInMinutes));
        }
    }
}
